#include "Esfera.h"
#include <cmath>

Esfera::Esfera(int _indice_textura, float _raio, const Ponto_3D& _centro) : Objeto_3D ( _indice_textura )
{
  raio = _raio;
  centro =  _centro;
}


//Foley capítulo 15.10, fórmula 15.17
const Objeto_3D* Esfera::Intercepta( Raio r_vis, float* t)const
{
  float distx, disty, distz, a, b, c, delta, raiz1, raiz2;

  // valores intermediários
  distx = r_vis.X0() - centro.X();
  disty = r_vis.Y0() - centro.Y();
  distz = r_vis.Z0() - centro.Z();

  // montando a equação do 2º grau at2 + bt + c = 0
  a = SQR(r_vis.Dx()) + SQR(r_vis.Dy()) + SQR(r_vis.Dz());
  b = 2 * ( r_vis.Dx() * distx + r_vis.Dy() * disty + r_vis.Dz() * distz );
  c = SQR(distx) + SQR(disty) + SQR(distz) - SQR(raio);

  // Calculando Delta
  delta = SQR(b) - 4*a*c;


  // Retornando t (se não existir t retornar valor negativo que será ignorado)
  if ( delta < 1 )
  {
      *t = -1.0;
      return(this);
  }

  delta = (float)sqrt(delta);
  a*=2;
  raiz1 = ( -b - delta ) / a;
  raiz2 = ( -b + delta ) / a;

  if(raiz1 > 0 && raiz2 > 0)
      *t = MINI(raiz1,raiz2);
  else
      if(raiz1 > 0)
          *t = raiz1;
      else
          *t = raiz2;


  return (this);
}

Vetor_3D Esfera::normal( const Ponto_3D& ponto ) const
{
    Vetor_3D tmp;

    tmp = ponto - centro;
    tmp.normaliza();

    return tmp;
}

TexturePoint Esfera::pontoTextura(const Ponto_3D& ponto) const
{
    float phi, theta;
    Vetor_3D tmp(ponto - centro);

    tmp.normaliza();

    phi  = acosf(tmp.Z());
    theta = acosf(tmp.X()/sin(phi));

    return TexturePoint((phi/M_PI), ((theta)/M_PI));
}
